import axios from 'axios';

import Config from '../../config';
import getAPIHeaders from '../get-api-headers';
import Member, { TopMemberResponse } from './member';

const memberEndpoint = '/member';

export default class MemberManager {
    static create = async (member: Partial<Member>): Promise<Member> => {
        const data = {
            member_ronin_wallet_address: member.memberRoninWalletAddress,
            manager_ronin_wallet_address: member.managerRoninWalletAddress,
            name: member.name,
            email: member.email,
        };

        const call = await axios.post(`${Config.getAPI()}${memberEndpoint}/create`, data, {
            headers: await getAPIHeaders(),
        });

        if (call.data?.error) {
            throw call.data.error;
        }

        if (call.data['member']) {
            return call.data['member'];
        }

        return null;
    };

    static update = async (member: Partial<Member>): Promise<Member> => {
        const data = {
            member_ronin_wallet_address: member.memberRoninWalletAddress,
            manager_ronin_wallet_address: member.managerRoninWalletAddress,
            name: member.name,
            email: member.email,
            member_id: member.id,
        };
        const call = await axios.put(`${Config.getAPI()}${memberEndpoint}/update`, data, {
            headers: await getAPIHeaders(),
        });

        if (call.data?.error) {
            throw call.data.error;
        }

        if (call.data['member']) {
            return call.data['member'];
        }

        return null;
    };

    static delete = async (id: string | number) => {
        const call = await axios.delete(
            `${Config.getAPI()}${memberEndpoint}/delete?member_id=${id}`,
            {
                headers: await getAPIHeaders(),
            }
        );

        if (call.data?.error) {
            throw call.data.error;
        }

        if (call.data) {
            return call.data;
        }

        return null;
    };

    static getList = async (page): Promise<{ hasMore: boolean; members: Member[] }> => {
        const call = await axios.get(`${Config.getAPI()}${memberEndpoint}/all?page=${page}`, {
            headers: await getAPIHeaders(),
        });

        if (call.data?.error) {
            throw call.data.error;
        }

        const result = {
            members: [],
            hasMore: false,
        };

        const { data = {} } = call;
        if (data && data.members) {
            const members: Member[] = [];

            for (let i = 0; i < data.members.length; i++) {
                members.push(Member.fromJSON(data.members[i]));
            }

            result.members = members;
            result.hasMore = !call.data.no_more_results;
        }

        return result;
    };

    static getAllList = async (page?: number, curr = []): Promise<Member[]> => {
        if (!page) {
            page = 0;
        }

        try {
            const { members, hasMore } = await MemberManager.getList(page);

            curr = [...curr, ...members];
            if (hasMore) {
                curr = await MemberManager.getAllList(page + 1, curr);
            }
        } catch (exception) {
            console.log(exception);
        }

        return curr;
    };

    static search = async (query): Promise<Member[]> => {
        const call = await axios.get(`${Config.getAPI()}${memberEndpoint}/search?query=${query}`, {
            headers: await getAPIHeaders(),
        });
        if (call.data?.error) {
            throw call.data.error;
        }

        const { data = {} } = call;
        if (data && data.members) {
            const { members } = data;

            return members;
        }

        return [];
    };

    static getTop = async (
        page = 0
    ): Promise<{ hasMore: boolean; members: TopMemberResponse[] }> => {
        const call = await axios.get(`${Config.getAPI()}${memberEndpoint}/top?page=${page}`, {
            headers: await getAPIHeaders(),
        });
        if (call.data?.error) {
            throw call.data.error;
        }

        const result = {
            members: [],
            hasMore: false,
        };

        const { data = {} } = call;
        if (data && data.members) {
            const { members } = data;

            result.members = members;
            result.hasMore = !call.data.no_more_results;
        }

        return result;
    };
}
